﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using MyMVCDemo.Models.EF;
using MyMVCDemo.Models.ViewModels.Account;
using MyMVCDemo.Models.Tools;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;

namespace MyMVCDemo.Services
{
    /// <summary>
    /// 账号相关服务
    /// </summary>
    public class AccountServices
    {
        private readonly MiniQQContext _context;
        private readonly IConfiguration _configuration;
        private readonly Random rnd;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public AccountServices(MiniQQContext context,IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
        {
            _context = context;
            _configuration = configuration;
            _httpContextAccessor = httpContextAccessor;
            rnd = new Random();
        }
        /// <summary>
        /// 返回指定的nickName是否被使用
        /// </summary>
        /// <param name="nickName"></param>
        /// <returns></returns>
        public async Task<bool> IsNickNameUsed(string nickName)
        {
            var ans =await _context.T001用户表s.AnyAsync(m => m.昵称 == nickName);
            return ans;
        }
        /// <summary>
        /// 注册 工具方法，使得EF数据更新，数据库数据更新
        /// </summary>
        /// <returns></returns>
        public async Task<string> Create(RegisterModel model)
        {
            string newQq = "";
            do
            {

                newQq = rnd.Next(10000, 99999).ToString();

                if (await _context.T001用户表s.AllAsync(m => m.Qq != newQq))
                {
                    break;
                }

            } while (true);

            var t001 = new T001用户表()
            {
                Qq = newQq,
                密码 = Utility.MD5(model.密码),
                昵称 = model.昵称,
                生日 = model.生日,
                邮箱 = model.邮箱,
                性别 = model.性别,
            };
            await _context.T001用户表s.AddAsync(t001);
            await _context.SaveChangesAsync();

            return newQq;

        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <returns></returns>
        public async Task<bool> Login(LoginModel model)
        {
            string pwd = Utility.MD5(model.密码);
            var item = await _context.T001用户表s.FirstOrDefaultAsync(m => m.Qq == model.Qq && m.密码 == pwd);
            //如果存在符合条件的记录，item=该记录，并返回，否则返回null
            if (item == null) return false;
            else
            {
                //新建claim记录，保存登录者信息。后续会继续用到。
                //claims可以理解为保存登录者信息的实例。
                //claimsIdentity就是访问者的“身份证明”，这些信息被存在cookies中

                //见： https://www.cnblogs.com/Ivan-Wu/p/10711288.html
                //登录的时候上传密码和名称到服务器中，如果匹配，那么服务器会将ClaimsIdentity保存到客户端中的cookies中，
                //然后每次请求需要验证的控制器的时候就会验证是否有ClaimIdentity。

                var claims = new List<Claim>
                    {
                        new Claim(ClaimTypes.Name, item.昵称),
                        new Claim(ClaimTypes.Sid,item.Qq),
                        new Claim(ClaimTypes.Role, "Member")
                    };

                var claimsIdentity = new ClaimsIdentity(claims,
                    CookieAuthenticationDefaults.AuthenticationScheme);

                await _httpContextAccessor.HttpContext.SignInAsync(
                    CookieAuthenticationDefaults.AuthenticationScheme,
                    new ClaimsPrincipal(claimsIdentity));
            }
            return true;
        }

        /// <summary>
        /// 注销
        /// </summary>
        /// <returns></returns>
        public async Task Logout()
        {
            await _httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

        }


        //只读属性
        public string MemberQq => _httpContextAccessor.HttpContext.User.FindFirst(System.Security.Claims.ClaimTypes.Sid)?.Value;
        public string MemberName => _httpContextAccessor.HttpContext.User.FindFirst(System.Security.Claims.ClaimTypes.Name)?.Value;
    
        
    
    }
}
